package com.deer.wms.ware.task.web;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.deer.wms.base.system.model.Area.AreaInfo;
import com.deer.wms.base.system.service.AreaInfoService;
import com.deer.wms.intercept.annotation.NoRepeatSubmit;
import com.deer.wms.intercept.annotation.User;
import com.deer.wms.intercept.common.data.CurrentUser;
import com.deer.wms.inventory.constant.InventoryConstant;
import com.deer.wms.inventory.model.Inventory.Inventory;
import com.deer.wms.inventory.model.Inventory.InventoryTransact;
import com.deer.wms.inventory.service.InventoryService;
import com.deer.wms.inventory.service.InventoryTransactService;
import com.deer.wms.project.root.core.result.CommonCode;
import com.deer.wms.project.root.exception.ServiceException;
import com.deer.wms.project.root.util.StringUtils;
import com.deer.wms.system.manage.model.user.UserInfo;
import com.deer.wms.system.manage.service.UserInfoService;
import com.deer.wms.ware.task.config.StrategyErpService;
import com.deer.wms.ware.task.model.SO.SoDetail;
import com.deer.wms.ware.task.model.SO.SoMaster;
import com.deer.wms.ware.task.model.Wave.*;
import com.deer.wms.ware.task.model.out.OutDetail;
import com.deer.wms.ware.task.model.pickTask.PickTask;
import com.deer.wms.ware.task.service.*;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.deer.wms.project.root.core.result.Result;
import com.deer.wms.project.root.core.result.ResultGenerator;
import springfox.documentation.annotations.ApiIgnore;

import javax.activation.DataHandler;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author wei
 * @date 2020/02/02
 */
@RestController
@RequestMapping("/wave/details")
public class WaveDetailController {

    @Autowired
    private WaveDetailService waveDetailService;
    @Autowired
    private WaveMasterService waveMasterService;
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private InventoryService inventoryService;
    @Autowired
    private SoDetailService soDetailService;
    @Autowired
    private SoMasterService soMasterService;
    @Autowired
    private OutMasterService outMasterService;
    @Autowired
    private InventoryTransactService inventoryTransactService;
    @Autowired
    private StrategyErpService strategyErpService;


    @PostMapping
    public Result add(@RequestBody WaveDetail waveDetail) {
        waveDetailService.save(waveDetail);
        return ResultGenerator.genSuccessResult();
    }

    @PostMapping("/addFromSo")
    public Result addFromSo(@RequestBody WaveDetailInsertData insertData) {
        WaveMaster wave = waveMasterService.getById(insertData.getWaveMasterId());
        for (Integer soId : insertData.getSoMasterIds()) {
            List<WaveDetailDto> waveDetail1 = waveDetailService.findList(new WaveDetailCriteria(soId));
            if (waveDetail1.size() > 0) {
                return ResultGenerator.genFailResult(CommonCode.SERVER_INERNAL_ERROR, "选中工单中有已添加批次", null);
            }
            WaveDetail waveDetail = new WaveDetail();
            waveDetail.setWaveMasterId(wave.getWaveId());
//            waveDetail.setSoMasterId(soId);
            waveDetailService.save(waveDetail);
        }
        return ResultGenerator.genSuccessResult();
    }

    @GetMapping("/delete")
    public Result delete(Integer id) {
        waveDetailService.removeById(id);
        return ResultGenerator.genSuccessResult();
    }

    @GetMapping("/sync/data")
    public Result syncCurrentData(String waveCode) {
        if (true) {
        throw new ServiceException(CommonCode.UPPER_TACTIC_ERROR,"按钮已关闭");
        }

        waveDetailService.syncCurrentData(waveCode);
        return ResultGenerator.genSuccessResult();
    }

    @GetMapping("/sendWaveDetail")
    public void sendWaveDetail() {
        waveDetailService.sendWaveDetail();
    }

    @PostMapping("/update")
    public Result update(@RequestBody WaveDetail waveDetail) {
        waveDetailService.updateById(waveDetail);
        return ResultGenerator.genSuccessResult();
    }

    @GetMapping("/{id}")
    public Result detail(@PathVariable Integer id, WaveDetailCriteria waveDetailCriteria) {

        waveDetailCriteria.setWaveId(id);

        WaveMaster waveMaster = waveMasterService.getById(id);

        //同步拉取触发
//        waveDetailService.syncCurrentData(waveMaster.getCode());

        if (ObjectUtil.isNotNull(waveDetailCriteria.getState())) {
            waveDetailCriteria.setStates(new Integer[]{waveDetailCriteria.getState()});
        }
        waveDetailCriteria.getItemCodes();
        List<WaveDetailDto> waveDetails = waveDetailService.findList(waveDetailCriteria);
        if (ObjectUtil.isEmpty(waveDetails)) {
            return ResultGenerator.genSuccessResult();
        }
        // 增加查询先发配件数量的更新
        waveDetails = waveDetailService.updateXfQuantity(waveDetails, id);


        return ResultGenerator.genSuccessResult(waveDetails);
    }


    @GetMapping
    public Result list(WaveDetailCriteria criteria) {

        PageHelper.startPage(criteria.getPageNum(), criteria.getPageSize());
        List<WaveDetailDto> list = waveDetailService.findList(criteria);
        PageInfo pageInfo = new PageInfo(list);
        return ResultGenerator.genSuccessResult(pageInfo);
    }

    @Autowired
    private PickTaskService pickTaskService;
    @Autowired
    private AreaInfoService areaInfoService;

    @GetMapping("/list/pick")
    public Result listForPick(WaveDetailCriteria criteria, @ApiIgnore @User CurrentUser currentUser) {
//        PageHelper.startPage(criteria.getPageNum(), criteria.getPageSize());
        criteria.setStates(new Integer[]{1, 2});
        criteria.setPickUserId(currentUser.getUserId());
        criteria.setIsAdmin(currentUser.getIsAdmin());
        List<WaveDetailDto> detailList = waveDetailService.findList(criteria);


        Set<Integer> waveDetailIds = detailList.stream().map(item -> item.getWaveDetailId()).collect(Collectors.toSet());
        if (ObjectUtil.isEmpty(waveDetailIds)) {
            return ResultGenerator.genSuccessResult();
        }
        List<PickTask> pickTasks = pickTaskService.list(new QueryWrapper<PickTask>().in("wave_detail_id", waveDetailIds)
                .eq("state", 0)
        );
        Map<Integer, List<PickTask>> pickMap = pickTasks.stream().collect(Collectors.groupingBy(PickTask::getWaveDetailId));


        Set<String> itemCodes = detailList.stream().map(item -> item.getItemCode()).collect(Collectors.toSet());
        List<Inventory> inventories = inventoryService.list(new QueryWrapper<Inventory>().in("item_code", itemCodes));
        List<AreaInfo> areaInfos = areaInfoService.list(new QueryWrapper<AreaInfo>().in("wave_type", 3, 1, 2));

        for (WaveDetailDto dto : detailList) {
            dto.setInvQty(waveDetailService.allInQty(inventories, dto.getItemCode(), areaInfos));
            List<PickTask> pickTasks1 = pickMap.get(dto.getWaveDetailId());
            if (ObjectUtil.isNotEmpty(pickTasks1)) {
            Set<String> set = pickTasks1.stream().map(PickTask::getCellCode).collect(Collectors.toSet());
            dto.setCellCodes(StringUtils.join(set, ","));
            }
        }
        PageInfo pageInfo = new PageInfo(detailList.stream().filter(item -> ObjectUtil.isNotEmpty(item.getCellCodes())).sorted(Comparator.comparing(WaveDetailDto::getCellCodes, Comparator.nullsLast(String::compareTo)))
                .limit(criteria.getPageSize()).collect(Collectors.toList()));
        return ResultGenerator.genSuccessResult(pageInfo);
    }



    @PostMapping("/suggest")
    @NoRepeatSubmit
    public Result suggestForPick(@RequestBody WaveDetailCriteria waveDetailCriteria, @ApiIgnore @User CurrentUser currentUser) {
        UserInfo wareUser = userInfoService.getById(waveDetailCriteria.getUserId());
        List<String> idsList = Arrays.asList(waveDetailCriteria.getIds().split(","));
        List<WaveDetail> waveDetailList = waveDetailService.listByIds(idsList);

        waveDetailService.suggestForPick(waveDetailList, wareUser, currentUser);
        return ResultGenerator.genSuccessResult();
    }

    @GetMapping("/sendOut")
    public Result sendOut(String pickIds, Integer wareId, @ApiIgnore @User CurrentUser currentUser) {
        if (currentUser == null) {
            return ResultGenerator.genFailResult(CommonCode.MISSING_PERMISSION_PARAMTER);
        }

        String[] split = pickIds.split(",");
        List<Integer> ids = new ArrayList<>();
        for (String s : split) {
            ids.add(Integer.valueOf(s));
        }

        Map<String, String> map = waveDetailService.sendOut(ids, currentUser);
        System.out.println(map);
        //出库单据回传erp
//        soMasterService.outbillToErpNew(billNo);
        return ResultGenerator.genSuccessResult(map);
    }


    @GetMapping("/downLoad")
    @ApiOperation(value = "波次导出", notes = "波次导出")
    public Result downLoad(String  waveCode, HttpServletResponse response) {
        waveDetailService.downLoad(waveCode, response);
        return ResultGenerator.genSuccessResult();
    }


    /**
     * 先发配件出库
     */
    @PostMapping("/xfPjCk")
    public Result xfPjCk(@RequestBody WaveDetailCriteria waveDetailCriteria, @ApiIgnore @User CurrentUser currentUser) {
        UserInfo wareUser = userInfoService.getById(waveDetailCriteria.getUserId());
        List<String> idsList = Arrays.asList(waveDetailCriteria.getIds().split(","));
        List<WaveDetail> waveDetailList = waveDetailService.listByIds(idsList);

        // 找到相应的出库任务明细 进行验收数量的扣减
        for (WaveDetail waveDetail : waveDetailList) {
            // 1.先查出与波次明细相关的出库明细
            List<SoDetail> soDetails = soDetailService.getListByField("wave_detail_id", waveDetail.getWaveDetailId());
            // 2.找到对应的出库任务(有先发配件库)
            for (SoDetail soDetail : soDetails) {
                SoMaster soMaster = soMasterService.getOneByField("bill_no", soDetail.getBillNo());
                QueryWrapper<Inventory> qw = Wrappers.query();
                Map<String, Object> map = new HashMap<>(4);
                //根据物料批次找到所有对应的库存
                map.put("ware_id", waveDetail.getWareId());
                // 增加筛选条件 库区 484153(先发配件库)
                map.put("erp_area_id", 484153);
                map.put("item_code", waveDetail.getItemCode());
//                map.put("batch_name", soMaster.getTradeNo());
                List<Inventory> inventories = inventoryService.getBaseMapper().selectList(qw.allEq(map, true));
                // 如果查出的库存为 0 证明不是先发配件物料
                if (inventories.size() > 0) {
                    // 修改相关明细的拣货完成数量
                    // 记录一下已经分配的数量
                    Double oldQty = soDetail.getAllottedQuantity();
                    // 还需分配的数量
                    Double qty = soDetail.getOrderQuantity() - soDetail.getAllottedQuantity();
                    if (waveDetail.getPreAllottedQuantity() > qty) {
                        //4.找到对应的出库任务明细
                        //5.修改验收数量
                        soDetail.setAllottedQuantity(soDetail.getOrderQuantity());
                        soDetail.setPickQuantity(soDetail.getOrderQuantity());
                        soDetail.setDeliveryQuantity(soDetail.getOrderQuantity());
                        // 将明细的预分配数进行扣减
                        waveDetail.setPreAllottedQuantity(waveDetail.getPreAllottedQuantity()
                                - qty);
                        // 更新出库任务明细信息
                        soDetailService.updateById(soDetail);
                    } else {
                        //4.找到对应的出库任务明细
                        //5.修改验收数量
                        soDetail.setAllottedQuantity(soDetail.getAllottedQuantity()
                                + waveDetail.getPreAllottedQuantity());
                        soDetail.setPickQuantity(soDetail.getAllottedQuantity());
                        soDetail.setDeliveryQuantity(soDetail.getAllottedQuantity());
                        // 将明细的预分配数进行扣减
                        waveDetail.setPreAllottedQuantity(0.0);
                        // 更新出库任务明细信息
                        soDetailService.updateById(soDetail);
                    }
                    // 创建出库单明细--所选择的库存是随机取得一个先发配件库存
                    OutDetail outDetail = new OutDetail(soDetail, inventories.get(0));
                    outDetail.setErpAreaId(484153);
                    // 设置发货数量
                    outDetail.setDeliveryQuantity(soDetail.getAllottedQuantity() - oldQty);
                    // 创建出库单
                    List<OutDetail> outDetailSet = new ArrayList<>();
                    outDetailSet.add(outDetail);
                    String outBill = outMasterService.createOutBill(soMaster, outDetailSet, currentUser);
                    // 出库数量
                    Double quantity = outDetail.getDeliveryQuantity();
                    // 扣减库存
                    for (Inventory inventory : inventories) {
                        // 创建库存事务
                        // 生成库存事务
                        InventoryTransact inventoryTransact = new InventoryTransact();
                        //Step1.准备数据
                        //仓库
                        inventoryTransact.setWareId(inventory.getWareId());
                        inventoryTransact.setWareName(inventory.getWareName());
                        //物料
                        inventoryTransact.setItemCode(inventory.getItemCode());
                        inventoryTransact.setItemName(inventory.getItemName());
                        //批次
                        inventoryTransact.setFromBatchId(inventory.getBatchId());
                        // 履约号--批次
                        inventoryTransact.setFromBatchName(inventory.getBatchName());
                        // 来源库位
                        inventoryTransact.setFromCellCode(inventory.getCellCode());
                        // 创建人 时间
                        inventoryTransact.setCreateUserId(currentUser.getUserId());
                        inventoryTransact.setCreateUserName(currentUser.getUserName());
                        inventoryTransact.setCreateTime(DateUtil.now());
                        //事务类型
                        inventoryTransact.setTransactType(InventoryConstant.INVENTORY_TYPE_OUT);
                        //来源单据号
                        inventoryTransact.setBillNo(outDetail.getDetailNo());
                        // 出库数量--增加判断
                        if (quantity > inventory.getQuantity()) {
                            // 库存不过扣减--先扣减当前数量 继续循环扣减下一个库位的库存
                            inventoryTransact.setFromQuantity(inventory.getQuantity());
                            //Step2.保存，返回
                            inventoryTransactService.save(inventoryTransact);
                            // 执行库存事务 -- 扣减库存
                            inventoryTransactService.run(inventoryTransact);
                            quantity -= inventory.getQuantity();
                        } else {
                            // 库存数量足够扣减
                            inventoryTransact.setFromQuantity(quantity);
                            //Step2.保存，返回
                            inventoryTransactService.save(inventoryTransact);
                            // 执行库存事务 -- 扣减库存
                            inventoryTransactService.run(inventoryTransact);
                            break;
                        }
                    }
                    // 进行ERP数据回传
//                    BaseAssist baseAssist=new BaseAssist();
//                    strategyErpService.resolveSo(soMaster,outDetailSet,baseAssist);
                }
            }
        }
        waveDetailList = waveDetailService.listByIds(idsList);
        // 扣减波次明细数据修改
        for (WaveDetail waveDetail : waveDetailList) {
            //计划数量,用预分配数量扣减--以后增加判断计划数量为0--删除波次明细
            waveDetail.setQuantity(waveDetail.getQuantity() - waveDetail.getPreAllottedQuantity());
            // 先发配件数量修改
            waveDetail.setXfQuantity(waveDetail.getXfQuantity() - waveDetail.getPreAllottedQuantity());
            // 预分配数量设置为0
            waveDetail.setPreAllottedQuantity(0.0);
            // 更新数据
            waveDetailService.updateById(waveDetail);
        }
        return ResultGenerator.genSuccessResult();
    }
}
